/**
 *******************************************************************************
 * @FileName  : tlsr825x_aes.c
 * @Author    : GaoQiu
 * @CreateDate: 2020-09-10
 * @Copyright : Copyright(C) GaoQiu
 *              All Rights Reserved.
 *
 *******************************************************************************
 *
 * The information contained herein is confidential and proprietary property of
 * GaoQiu and is available under the terms of Commercial License Agreement
 * between GaoQiu and the licensee in separate contract or the terms described
 * here-in.
 *
 * This heading MUST NOT be removed from this file.
 *
 * Licensees are granted free, non-transferable use of the information in this
 * file under Mutual Non-Disclosure Agreement. NO WARRENTY of ANY KIND is provided.
 *
 *******************************************************************************
 */
#include "tlsr825x_aes.h"

/**
 * @brief : AES common handler
 * @param : out     pointer point to out buffer.
 * @param : in      pointer point to in buffer.
 * @param : key     pointer point to key.
 * @return: none.
 */
RAM_CODE void AES_Common(uint8_t out[16], uint8_t in[16], uint8_t key[16])
{
	uint32_t value = 0;
	__IO uint32_t *pKey = (__IO uint32_t *)&AES->KEY0;
	uint8_t  *p = NULL;

	/* Set Key */
	p = key;
	for(int i=0; i<4; i++)
	{
		value = (p[3]<<24)|(p[2]<<16)|(p[1]<<8)|(p[0]);
		*pKey = value;

		p += 4;
		pKey++;
	}

	/* Set data */
	p = in;
	while(AES->CTRL & AES_CTRL_INPUT_DATA_NEEDED){
		AES->DAT = (p[3]<<24)|(p[2]<<16)|(p[1]<<8)|(p[0]);
		p += 4;
	}

	/* Wait operation complete. */
	while(!(AES->CTRL & AES_CTRL_OUTPUT_DATA_READY));

	/* Get data */
	p = out;
	for(int i=0; i<4; i++)
	{
		value  = AES->DAT;
		*out++ =  (uint8_t)value;
		*out++ =  (uint8_t)(value>>8);
		*out++ =  (uint8_t)(value>>16);
		*out++ =  (uint8_t)(value>>24);
	}
}

/**
 * @brief : AES common handler
 * @param : out     pointer point to out buffer.
 * @param : in      pointer point to in buffer.
 * @param : key     pointer point to key.
 * @return: none.
 */
RAM_CODE void AES_CommonBigEndian(uint8_t out[16], uint8_t in[16], uint8_t key[16])
{
	uint32_t value = 0;
	uint32_t *pKey = (uint32_t *)&AES->KEY0;
	uint8_t  *p = NULL;

	/* Set Key */
	p = key;
	for(int i=0; i<16; i+=4){
		*pKey = (p[12-i]<<24)|(p[13-i]<<16)|(p[14-i]<<8)|(p[15-i]);
		pKey++;
	}

	/* Set data */
	p = in;
	int i = 0;
	while(AES->CTRL & AES_CTRL_INPUT_DATA_NEEDED)
	{
		AES->DAT = (p[12-i]<<24)|(p[13-i]<<16)|(p[14-i]<<8)|(p[15-i]);
		i+=4;
	}

	/* Wait operation complete. */
	while(!(AES->CTRL & AES_CTRL_OUTPUT_DATA_READY));

	/* Get data */
	p = out;
	for(int i=0; i<4; i++)
	{
		value  = AES->DAT;
		*out++ =  (uint8_t)value;
		*out++ =  (uint8_t)(value>>8);
		*out++ =  (uint8_t)(value>>16);
		*out++ =  (uint8_t)(value>>24);
	}
}

/**
 * @brief : AES encrypt data.
 * @param : out     pointer point to out buffer.
 * @param : in      pointer point to in buffer.
 * @param : key     pointer point to key.
 * @return: none.
 */
bool_t AES_Encrypt(uint8_t out[16], uint8_t in[16], uint8_t key[16])
{
	//AES->CTRL = 0x00;
	AES->CTRL  &= ~AES_CTRL_DECRYPT; //trigger encrypt
	AES_Common(out, in, key);
	return true;
}

/**
 * @brief : AES decrypt data.
 * @param : out     pointer point to out buffer.
 * @param : in      pointer point to in buffer.
 * @param : key     pointer point to key.
 * @return: none.
 */
bool_t AES_Decrypt(uint8_t out[16], uint8_t in[16], uint8_t key[16])
{
	AES->CTRL |= AES_CTRL_DECRYPT;//trigger decrypt
	AES_Common(out, in, key);
	return true;
}

/**
 * @brief : AES encrypt data.
 * @param : out     pointer point to out buffer. big-endian
 * @param : in      pointer point to in buffer.  little-endian
 * @param : key     pointer point to key.        little-endian
 * @return: none.
 */
bool_t AES_EncryptBigEndian(uint8_t out[16], uint8_t in[16], uint8_t key[16])
{
	AES->CTRL = 0x00;
	AES_CommonBigEndian(out, in, key);
	return true;
}
